package com.cw.jeeyt.service.utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cw.jeeyt.service.bo.system.SystemAttachBo;

/**
 * @author fengmq
 */
public class FileTools {
    final static Logger log = LoggerFactory.getLogger(FileTools.class);

    /**
     * 将指定文件拷贝到指定目录下
     *
     * @param filePath
     * @param targetFile
     * @return
     */
    public static boolean copyFileToSpecialDirectory(String filePath, String targetFile) {
        FileInputStream in = null;
        FileOutputStream out = null;
        byte[] buffer = new byte[1024];
        try {
            in = new FileInputStream(filePath);
            File dest = new File(targetFile);
            if (!dest.exists()) {// 目标文件对应的目录不存在，创建新的目录
                int index = targetFile.lastIndexOf("/");
                if (index > 0) {
                    String path = targetFile.substring(0, index);
                    new File(path).mkdirs();
                }
            }
            out = new FileOutputStream(targetFile);
            int num = 0;
            while ((num = in.read(buffer)) != -1) {
                out.write(buffer, 0, num);
            }
        } catch (FileNotFoundException ex) {
            log.error(ex.getMessage());
            return false;
        } catch (IOException e) {
            log.error(e.getMessage());
            return false;
        } finally {
            try {
                if (in != null)
                    in.close();
                if (out != null)
                    out.close();
            } catch (IOException ex) {
                log.error(ex.getMessage());
            }
        }
        return true;
    }

    /**
     * 获取指定文件的内容，返回字符串
     *
     * @param filePath
     * @return
     * @throws FileNotFoundException
     */
    public static String getFileContentByPath(String filePath) {
        StringBuffer content = new StringBuffer();
        try {
            File file = new File(filePath);
            InputStreamReader is = new InputStreamReader(new FileInputStream(file), "UTF-8");
            BufferedReader reader = new BufferedReader(is);
            String line = "";
            while ((line = reader.readLine()) != null) {
                content.append(line + "\n");
            }
            reader.close();
        } catch (Exception e) {
            log.error("Error when get file  content by path: " + filePath, e);
            return "";
        }
        return content.toString();
    }

    /**
     * 下载文件
     *
     * @param response
     * @throws IOException
     */
    public static void downloadFile(HttpServletResponse response, SystemAttachBo systemAttachBo) throws IOException {
        OutputStream out = response.getOutputStream();
        String sExt = systemAttachBo.getContentType();
        // 文件格式为pdf、doc、xml格式的直接用浏览器打开。其他提示下载或者打开
        if (sExt.equals("application/pdf") || sExt.equals("image/pjpeg") || sExt.equals("image/bmp") || sExt.equals(
            "application/vnd.ms-powerpoint") || sExt.equals("text/plain") || sExt.equals("application/msword")
            || sExt.equals("text/plain") || sExt.equals("application/vnd.ms-excel")) {
            if (sExt.equals("application/pdf"))
                response.setContentType(sExt);
            else
                response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition", "inline;filename=" + new String(systemAttachBo.getFileName()
                .getBytes("GBK"), "ISO8859_1"));
        } else {
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(systemAttachBo.getFileName()
                .getBytes("GBK"), "ISO8859_1"));
        }

        InputStream is = null;
        if (systemAttachBo.getContent() != null && systemAttachBo.getContent().length > 0) {
            is = new ByteArrayInputStream(systemAttachBo.getContent());
        } else {
            is = new FileInputStream(systemAttachBo.getFileDir() + systemAttachBo.getFileName());
        }
        outputAttachFileStream(out, is);
    }

    /**
     * 输出文件
     *
     * @param out
     * @param inputStream
     * @throws IOException
     */
    public static void outputAttachFileStream(OutputStream out, InputStream inputStream) throws IOException {
        byte[] buffer = new byte[102400];
        try {
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
        } catch (Exception e) {
            System.err.println("用户取消下载或下载正文出错！");
        } finally {
            if (out != null) {
                out.close();
            }
            out = null;
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

    // 获取文件类型
    public static String getFileExtention(String sExt) {
        sExt = sExt.toLowerCase();
        if (sExt.indexOf("/") > 0)
            return sExt;
        else if (sExt.equals("jpg") || sExt.equals("jpeg"))
            return "image/pjpeg";
        else if (sExt.equals("bmp"))
            return "image/bmp";
        else if (sExt.equals("doc") || sExt.equals("rtf"))
            return "application/msword";
        else if (sExt.equals("pdf"))
            return "application/pdf";
        else if (sExt.equals("ppt"))
            return "application/vnd.ms-powerpoint";
        else if (sExt.equals("txt") || sExt.equals("pas") || sExt.equals("cpp") || sExt.equals("c") || sExt.equals(
            "java") || sExt.equals("xml") || sExt.equals("ini"))
            return "text/plain";
        else if (sExt.equals("xls") || sExt.equals("cvs"))
            return "application/vnd.ms-excel";
        else if (sExt.equals("mp3"))
            return "audio/mpeg";
        else if (sExt.equals("wma") || sExt.equals("avi"))
            return "audio/x-ms-wma";
        else if (sExt.equals("wmv"))
            return "video/x-ms-wmv";
        else if (sExt.equals("zip"))
            return "application/x-zip-compressed";
        else
            return "application/octet-stream";
    }

    // 获取文件类型
    public static String getFileExtentionByOriginalFileName(String fileName) {
        if (fileName.indexOf(".") != -1) {
            return getFileExtention(fileName.substring(fileName.lastIndexOf(".") + 1));
        } else {
            return "无扩展名";
        }
    }

    /**
     * 从文件全路径名中得到文件名。
     *
     * @param filePath
     * @return
     */
    public static String getFileName(String filePath) {
        File file = new File(filePath);
        return file.getName();
    }

    /**
     * 从文件全路径名中得到文件路径。
     *
     * @param fileName
     * @return
     */
    public static String getFilePath(String fileName) {
        File file = new File(fileName);
        return file.getParent();
    }

    /**
     * 从文件全路径名中得到文件的扩展名
     *
     * @param fileName
     * @return
     */
    public static String getTypePart(String fileName) {
        int point = fileName.lastIndexOf('.');
        int length = fileName.length();
        if (point == -1 || point == length - 1) {
            return "";
        } else {
            return fileName.substring(point + 1, length);
        }
    }

    /**
     * 判断文件(文件或者路径)是否存在
     *
     * @param pathName
     * @return
     */
    public static boolean judgeFileExist(String pathName) {
        File temp = new File(pathName);
        return temp.exists();
    }

    /**
     * 创建文件夹，如果文件夹已经存在，则不做处理
     *
     * @param pathName
     */
    public static void createDirectory(String pathName) {
        File temp = new File(pathName);
        if (!temp.exists()) {
            temp.mkdirs();
        }
    }

    /**
     * 将Byte字节信息写入文件
     *
     * @param Path 路径
     * @param FileName 文件名
     * @param Data 需要写入的数据
     * @throws IOException
     */
    public static void writeFile(String Path, String FileName, byte[] Data) throws IOException {
        createDirectory(Path);
        File temp = new File(Path, FileName);
        DataOutputStream outs = new DataOutputStream(new FileOutputStream(temp));
        outs.write(Data);
        outs.close();
    }

    /**
     * 读文件信息得到Byte数组
     *
     * @param FileName
     * @return
     * @throws IOException
     */
    public static byte[] readFile(String FileName) throws IOException {
        File file = new File(FileName);
        byte[] data = new byte[(int) file.length()];
        FileInputStream fis = null;
        fis = new FileInputStream(file);
        fis.read(data, 0, data.length);
        fis.close();
        return data;
    }

    /**
     * 拷贝文件夹中的所有文件到另外一个文件夹
     *
     * @param srcDirector
     * @param desDirector
     * @throws IOException
     */
    public static void copyFileWithDirector(String srcDirector, String desDirector) throws IOException {
        (new File(desDirector)).mkdirs();
        File[] file = (new File(srcDirector)).listFiles();
        for (int i = 0; i < file.length; i++) {
            if (file[i].isFile()) {
                FileInputStream input = new FileInputStream(file[i]);
                FileOutputStream output = new FileOutputStream(desDirector + "/" + file[i].getName());
                byte[] b = new byte[1024 * 5];
                int len;
                while ((len = input.read(b)) != -1) {
                    output.write(b, 0, len);
                }
                output.flush();
                output.close();
                input.close();
            }
            if (file[i].isDirectory()) {
                copyFileWithDirector(srcDirector + "/" + file[i].getName(), desDirector + "/" + file[i].getName());
            }
        }
    }

    /**
     * 含通配符文件名匹配，支持？和 *
     *
     * @param pattern
     * @param string
     * @return
     */
    public static boolean matchString(String pattern, String string) {
        int stringLength = string.length();
        int stringIndex = 0;
        for (int patternIndex = 0; patternIndex < pattern.length(); ++patternIndex) {
            char c = pattern.charAt(patternIndex);
            if (c == '*') {
                while (stringIndex < stringLength) {
                    if (matchString(pattern.substring(patternIndex + 1), string.substring(stringIndex))) {
                        return true;
                    }
                    ++stringIndex;
                }
            } else if (c == '?') {
                ++stringIndex;
                if (stringIndex > stringLength) {
                    return false;
                }
            } else {
                if (stringIndex >= stringLength || c != string.charAt(stringIndex)) {
                    return false;
                }
                ++stringIndex;
            }
        }
        return stringIndex == stringLength;
    }

    /**
     * 支持通配符的文件搜索
     *
     * @param filePath
     * @param fileNamePattern
     * @param bProcessSonPath 是否处理子目录
     * @return
     */
    public static String[] searchFiles(String filePath, String fileNamePattern, boolean bProcessSonPath) {
        if (filePath.endsWith(File.separator)) {
            filePath = filePath + File.separator;
        }
        List<File> fileList = new ArrayList<File>();
        QueueTool queue = new QueueTool();
        queue.add(new File(filePath));
        File curFile = null;
        while (!queue.isEmpty()) {
            curFile = (File) queue.pop();
            if (curFile.exists() && curFile.isDirectory()) {
                File[] files = curFile.listFiles();
                for (int i = 0; i < files.length; i++) {
                    if (files[i].isDirectory()) {
                        if (bProcessSonPath) {
                            queue.add(files[i]);
                        }
                    } else {
                        if (matchString(fileNamePattern.toLowerCase(), files[i].getName()
                            .toLowerCase())) {
                            fileList.add(files[i].getAbsoluteFile());
                        }
                    }
                }
            }
        }
        String[] fileStrings = new String[fileList.size()];
        for (int i = 0; i < fileStrings.length; i++) {
            fileStrings[i] = fileList.get(i)
                .getAbsolutePath();
        }
        return fileStrings;
    }

    /**
     * 获取文件的相对路径
     *
     * @param fileAllName
     * @param filePath
     * @return
     */
    public static String getRelativePath(String fileAllName, String filePath) {
        File file1 = new File(fileAllName);
        File file2 = new File(filePath);
        String fileName1 = file1.getParent()
            .trim();
        String fileName2 = file2.getAbsolutePath()
            .trim();
        if (fileName1.startsWith(fileName2)) {
            if (fileName1.length() > fileName2.length()) {
                fileName1 = fileName1.substring(fileName2.length() + 1);
                return fileName1;
            } else {
                return "";
            }
        } else {
            return "";
        }
    }

    /**
     * 文件复制
     *
     * @param filefrom 源文件
     * @param fileto 目的文件
     * @param rewrite 是否覆盖
     * @return
     * @throws IOException
     */
    public static boolean copyFile(File filefrom, File fileto, boolean rewrite) throws IOException {
        if (!filefrom.exists()) {
            return false;
        }
        if (!filefrom.isFile()) {
            return false;
        }
        if (!filefrom.canRead()) {
            return false;
        }
        if (!fileto.getParentFile()
            .exists()) {
            fileto.getParentFile()
                .mkdirs();
        }
        if (fileto.exists() && rewrite) {
            fileto.delete();
        }
        FileInputStream fosfrom = new FileInputStream(filefrom);
        FileOutputStream fosto = new FileOutputStream(fileto);
        byte bt[] = new byte[1024];
        int c;
        while ((c = fosfrom.read(bt)) > 0) {
            fosto.write(bt, 0, c);
        }
        fosfrom.close();
        fosto.close();
        return true;
    }

    /**
     * 文件复制
     *
     * @param from 源文件名
     * @param to 目标文件名
     * @param rewrite 是否覆盖
     * @return
     * @throws IOException
     */
    public static boolean copyFile(String from, String to, boolean rewrite) throws IOException {
        File filefrom = new File(from);
        File fileto = new File(to);
        return copyFile(filefrom, fileto, rewrite);
    }

    /**
     * 删除文件或者文件夹
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    public static void deleteFile(String fileName) throws IOException {
        File file = new File(fileName);
        if (file.isFile()) {
            if (!file.delete()) {
                Runtime rt = Runtime.getRuntime();
                rt.exec("cmd   /c   del   " + fileName);
            }
        } else {
            if (!fileName.endsWith(File.separator)) {
                fileName = fileName + "\\";
            }
            String[] fileStrings = file.list();
            for (int i = 0; i < fileStrings.length; i++) {
                deleteFile(fileName + fileStrings[i]);
            }
            if (!file.delete()) {
                Runtime rt = Runtime.getRuntime();
                rt.exec("cmd   /c   del   " + fileName);
            }
        }
    }

    /**
     * 获取文件大小
     *
     * @param fileName
     * @return byte字节数
     */
    public static long getFileSize(String fileName) {
        File file = new File(fileName);
        return file.length();
    }

    /**
     * Bytes 转换为 G、M、K
     *
     * @param size 大小
     * @return
     */
    public static String getFileSizeString(long size) {
        String result = "";
        if (size < 0)
            return "0B";
        if (size >= 1024) {
            size = (long) Math.ceil(size / 1024);
            if (size / 1048576 >= 1) {
                size = size / 1024;
                DecimalFormat df = new DecimalFormat(".00");
                result = df.format(size / 1024f) + "G";
            } else if (size / 1024 >= 1) {
                DecimalFormat df = new DecimalFormat(".00");
                result = df.format(size / 1024f) + "M";
            } else
                result = size + "K";
        } else {
            result = size + "B";
        }
        return result;
    }

    /**
     * 获取文件最后更新时间
     *
     * @param fileName
     * @return
     */
    public static Date getFileUptimeTime(String fileName) {
        File file = new File(fileName);
        if (!file.exists()) {
            return null;
        }
        return new Date(file.lastModified());
    }

    /**
     * 根据字符串创建文件到指定目录
     *
     * @param fileName 文件存放路径和名称
     * @param fileContent 文件内容
     * @return
     * @throws IOException
     */
    public static void createFileToDirectoryByString(String fileName, String fileContent) throws IOException {
        File javaFile = new File(fileName);
        OutputStream ou = new FileOutputStream(javaFile);
        BufferedWriter rd = new BufferedWriter(new OutputStreamWriter(ou, "utf-8"));
        rd.write(fileContent);
        rd.close();
        ou.close();
    }

    /**
     * 输出文件
     *
     * @param out
     * @param inputStream
     * @throws IOException
     */
    public static void outputFileStream(OutputStream out, InputStream inputStream) throws IOException {
        byte[] buffer = new byte[102400];
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
        if (out != null) {
            out.close();
            out = null;
        }

        if (inputStream != null) {
            inputStream.close();
            inputStream = null;
        }
    }

}
